/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.vng.zing.lib;

import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;

/**
 *
 * @author tiepvv
 */
public class ZStat {

    static class StatItem {

        public AtomicLong _totalHits = new AtomicLong();
        public ZDayStat __hitInSecond = new ZDayStat();
        public ZDayStat __timeExecutedInSecond = new ZDayStat();

        public void clearSecondsData() {
            __hitInSecond.clear();
            __timeExecutedInSecond.clear();
        }

        public void clearTotalHits() {
            _totalHits.set(0);
        }
    };
    private static int FCOUNT = 10;
    private StatItem[] stats;
    private int currentDay;

    public ZStat() {
        stats = new StatItem[FCOUNT];
        for (int i = 0; i < FCOUNT; i++) {
            stats[i] = new StatItem();
        }
    }

    public void addCurrentRequest(int fid, long execTime) {
        // May be conflict
        if (fid < FCOUNT) {
            stats[fid]._totalHits.incrementAndGet();
            int _cd = Calendar.DAY_OF_YEAR;
            if (_cd != currentDay) {
                currentDay = _cd;
                stats[fid].clearSecondsData();
            }
            int second = getCurrentSecond();
            stats[fid].__hitInSecond.inc(second);
            stats[fid].__timeExecutedInSecond.set(second, execTime);

        }
    }

    /**
     * Print Readable timeformat
     *
     * @param val
     * @return
     */
    public String printDateTime(long val) {
        return "";
    }

    public String printStat(String methodMaps[]) {
        int second = getCurrentSecond();
        StringBuilder output = new StringBuilder();
        output.append("----------------------------------------------------------------------------------------------------------------------------------------------------\n");
        output.append("Method\t\t  Total Request\t Last RPS/ Last Exe Time\t\tMax RPS      Min RPS      Avg RPS      Max ExeT      Min ExeT      Avg ExeT\n");
        output.append("----------------------------------------------------------------------------------------------------------------------------------------------------\n");

        for (int i = 0; i < FCOUNT - 1; i++) {
            // append method
            output.append(padRight(methodMaps[i], 19));
            output.append(padRight(String.format("%,d", stats[i]._totalHits.get()), 14));
            if (second > 5) {
                StringBuilder lastRPS = new StringBuilder();
                lastRPS.append(String.format("%,d", stats[i].__hitInSecond.get(second - 1))).append(" ");
                lastRPS.append(String.format("%,d", stats[i].__hitInSecond.get(second - 2))).append(" ");
                lastRPS.append(String.format("%,d", stats[i].__hitInSecond.get(second - 3))).append(" ");
                lastRPS.append(String.format("%,d", stats[i].__hitInSecond.get(second - 4))).append(" ");
                lastRPS.append(String.format("%,d", stats[i].__hitInSecond.get(second - 5)));
                output.append(padRight(lastRPS.toString(), 39));
            }
            if (second > 60) {
                output.append(padRight(String.format("%s", maxRpsFromDate(i, second - 60, second)), 13));
                output.append(padRight(String.format("%s", minRpsFromDate(i, second - 60, second)), 13));
                output.append(padRight(String.format("%.3f", avgRpsFromDate(i, second - 60, second)), 13));

                output.append(padRight(String.format("%s", maxExeTFromDate(i, second - 60, second)), 14));
                output.append(padRight(String.format("%s", minExeTFromDate(i, second - 60, second)), 14));
                output.append(padRight(String.format("%.3f", avgExeTFromDate(i, second - 60, second)), 10));
            }
            output.append("\n");
            if (second > 5) {
                StringBuilder lastExeT = new StringBuilder();
                lastExeT.append(String.format("%,d", stats[i].__timeExecutedInSecond.get(second - 1))).append(" ");
                lastExeT.append(String.format("%,d", stats[i].__timeExecutedInSecond.get(second - 2))).append(" ");
                lastExeT.append(String.format("%,d", stats[i].__timeExecutedInSecond.get(second - 3))).append(" ");
                lastExeT.append(String.format("%,d", stats[i].__timeExecutedInSecond.get(second - 4))).append(" ");
                lastExeT.append(String.format("%,d", stats[i].__timeExecutedInSecond.get(second - 5)));
                output.append("\t\t\t\t ").append(lastExeT.toString());
            }
            output.append("\n");
        }        
        return output.toString();
    }

    public int maxRpsFromDate(int fid, int from, int to) {
        if (fid < 0 || fid > FCOUNT) {
            return -1;
        }
        return (int) stats[fid].__hitInSecond.maxDataFromDate(from, to);
    }

    public int minRpsFromDate(int fid, int from, int to) {
        if (fid < 0 || fid > FCOUNT) {
            return -1;
        }
        return (int) stats[fid].__hitInSecond.minDataFromDate(from, to);
    }

    public float avgRpsFromDate(int fid, int from, int to) {
        if (fid < 0 || fid > FCOUNT) {
            return -1;
        }
        return stats[fid].__hitInSecond.avgDataFromDate(from, to);
    }

    public int maxExeTFromDate(int fid, int from, int to) {
        if (fid < 0 || fid > FCOUNT) {
            return -1;
        }
        return (int) stats[fid].__timeExecutedInSecond.maxDataFromDate(from, to);
    }

    public int minExeTFromDate(int fid, int from, int to) {
        if (fid < 0 || fid > FCOUNT) {
            return -1;
        }
        return (int) stats[fid].__timeExecutedInSecond.minDataFromDate(from, to);
    }

    public float avgExeTFromDate(int fid, int from, int to) {
        if (fid < 0 || fid > FCOUNT) {
            return -1;
        }
        return stats[fid].__timeExecutedInSecond.avgDataFromDate(from, to);
    }

    public int getRpsDataFromDate(int fid, int from, int to, List<Long> rpsData) {
        if (fid < 0 || fid > FCOUNT) {
            return -1;
        }
        return (int) stats[fid].__hitInSecond.getDataFromDate(from, to, rpsData);
    }

    private static int getCurrentSecond() {
        Date current = new Date();
        return current.getHours() * 60 * 60 + current.getMinutes() * 60 + current.getSeconds();
    }

    public static String padRight(String s, int n) {
        return String.format("%1$-" + n + "s", s);
    }

    public static String padLeft(String s, int n) {
        return String.format("%1$" + n + "s", s);
    }
}
